package com.fingard.dsp.bank.directbank.ccb02;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directbank.bankInterface.IBalance;
import com.fingard.dsp.bank.reqrespobj.balance.Req7505HisBalQry;
import com.fingard.dsp.bank.reqrespobj.balance.Req7506BalQry;
import com.fingard.dsp.bank.reqrespobj.balance.RetAts7505HisBalQry;
import com.fingard.dsp.bank.reqrespobj.balance.RetAts7506BalQry;
import com.fingard.dsp.bank.reqrespobj.balance.detail.RetAtsBalDetail;
import com.fingard.dsp.bank.reqrespobj.balance.detail.RetAtsHisBalDetail;
import com.fingard.dsp.bank.reqrespobj.enumeration.ENDirectRight;
import com.fingard.text.StringHelper;
import com.fingard.util.DateHelper;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import java.text.DateFormat;
import java.util.Date;

public class CCB02Balance extends CCB02Base implements IBalance {

    //单个余额查询和批量余额查询，统一采用流处理方式
    //1、循环调用Req7506BalQry.readRecord()读取一个请求明细，然后写入发银行的XML对象
    //2、发银行
    //3、循环调用XmlTextReader.read()读取一个银行返回节点，赋值返回ATS的明细对象，
    //   然后调用RetAts7506BalQry.writeRetDetail()，写入返回ATS的明细
    @Override
    public RetAts7506BalQry d_7506_BalQry(Req7506BalQry p_req7506) throws Exception {//余额查询
        //余额查询返回ATS的对象
        RetAts7506BalQry retAts = new RetAts7506BalQry(p_req7506.reqHeader);
        retAts.writeStart();//写返回ATS的统一头部信息
        try {
            while (p_req7506.readRecord()) {
                if (p_req7506.readedDetail.actBankType.equals("13")) {
                    //结构账户标志为现金池账户或者有直联现金池权限
                    d_6WCZ01_BalQry(p_req7506, retAts);
                } else {
                    d_6W0100_BalQry(p_req7506, retAts);
                }
            }
        } catch (Exception e) {
            retAts.writeRespCode("-1");
            retAts.writeRespInfo(e.getMessage());
            e.printStackTrace();
        }
        retAts.writeEnd();
        return retAts;
    }

    //现金池余额查询接口
    public void d_6WCZ01_BalQry(Req7506BalQry p_req7506, RetAts7506BalQry retAts) throws Exception {
        RetAtsBalDetail tmpRetDetail = new RetAtsBalDetail();
        WriteBankLogLn("进入6WCZ01余额查询接口...");
        try {
            //赋值通用参数
            CCB02Header bankHeader = new CCB02Header();
            bankHeader.TX_CODE = "6WCZ01";
            bankHeader.REQUEST_SN = getQryTransID();
            tmpRetDetail.actNum = p_req7506.readedDetail.actNum;

            XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
            //写入通用的头部节点
            writeCommonHeader(xmlWriter, bankHeader);
            xmlWriter.writeStartElement("TX_INFO");
            if (!StringHelper.isNullOrEmpty(p_req7506.readedDetail.higherLevelAct)) {
                xmlWriter.writeElementString("ACC_NO", p_req7506.readedDetail.higherLevelAct);//主账号
                xmlWriter.writeElementString("ACCT_NO", p_req7506.readedDetail.actNum);//子账号
            } else {
                xmlWriter.writeElementString("ACC_NO", p_req7506.readedDetail.actNum);//主账号
                xmlWriter.writeElementString("ACCT_NO", p_req7506.readedDetail.actNum);//子账号
            }
            xmlWriter.writeEndDocument();

            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString(), p_req7506.reqHeader.transType, p_req7506.reqHeader.transType);

            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpRetCode = tmpBkReader.getFirstText("/TX/RETURN_CODE");
                    String tmpRetInfo = tmpBkReader.getFirstText("/TX/RETURN_MSG");
                    if (tmpRetCode != null && tmpRetCode.equals("000000")) {
                        if (tmpBkReader.read("/TX/TX_INFO")) {
                            tmpRetDetail.respCode = "0";
                            tmpRetDetail.actCur = p_req7506.readedDetail.actCur;
                            tmpRetDetail.actNum = p_req7506.readedDetail.actNum;
                            tmpRetDetail.currBal = tmpBkReader.readedXElement.getSingleText("BAL");
                            tmpRetDetail.frozenBal = tmpBkReader.readedXElement.getSingleText("FRZ_AMT");
                            tmpRetDetail.cashPoolBal = tmpBkReader.readedXElement.getSingleText("CASH_POOL_AMT");
                        }
                    } else {
                        tmpRetDetail.respCode = "-1";
                        tmpRetDetail.respInfo = tmpRetInfo;
                    }
                } else {
                    tmpRetDetail.respCode = "-1";
                    tmpRetDetail.respInfo = tmpSbMsg.toString();
                }
            } else {
                tmpRetDetail.respCode = "-1";
                tmpRetDetail.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            tmpRetDetail.respCode = "-1";
            tmpRetDetail.respInfo = "账号：" + p_req7506.readedDetail.actNum + ",现金池余额查询报错,详情查看日志";
            WriteBankLogLn("账号：" + p_req7506.readedDetail.actNum + ",现金池余额查询报错：" + e.getMessage());
        }
        retAts.writeRetDetail(tmpRetDetail, p_req7506.isBatch);
    }

    //普通余额查询接口
    public void d_6W0100_BalQry(Req7506BalQry p_req7506, RetAts7506BalQry retAts) throws Exception {
        RetAtsBalDetail tmpRetDetail = new RetAtsBalDetail();
        WriteBankLogLn("进入6W0100余额查询接口...");
        try {
            //赋值通用参数
            CCB02Header bankHeader = new CCB02Header();
            bankHeader.TX_CODE = "6W0100";
            bankHeader.REQUEST_SN = getQryTransID();
            tmpRetDetail.actNum = p_req7506.readedDetail.actNum;

            XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
            //写入通用的头部节点
            writeCommonHeader(xmlWriter, bankHeader);
            xmlWriter.writeStartElement("TX_INFO");
            xmlWriter.writeElementString("ACC_NO", p_req7506.readedDetail.actNum);
            xmlWriter.writeEndElement();
            xmlWriter.writeEndDocument();
            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString(), p_req7506.reqHeader.transType, "6W0100");
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpRetCode = tmpBkReader.getFirstText("/TX/RETURN_CODE");
                    String tmpRetInfo = tmpBkReader.getFirstText("/TX/RETURN_MSG");
                    if (tmpRetCode != null && tmpRetCode.equals("000000")) {
                        if (tmpBkReader.read("/TX/TX_INFO")) {
                            tmpRetDetail.respCode = "0";
                            tmpRetDetail.actCur = p_req7506.readedDetail.actCur;
                            tmpRetDetail.actNum = p_req7506.readedDetail.actNum;
                            tmpRetDetail.currBal = tmpBkReader.readedXElement.getSingleText("BALANCE");
                            tmpRetDetail.availBal = tmpBkReader.readedXElement.getSingleText("BALANCE1");
                            if (StringHelper.isNullOrEmpty(tmpRetDetail.availBal)) {
                                tmpRetDetail.availBal = tmpRetDetail.currBal;
                            }
                        }
                    } else {
                        tmpRetDetail.respCode = "-1";
                        tmpRetDetail.respInfo = tmpRetInfo;
                    }
                } else {
                    tmpRetDetail.respCode = "-1";
                    tmpRetDetail.respInfo = tmpSbMsg.toString();
                }
            } else {
                tmpRetDetail.respCode = "-1";
                tmpRetDetail.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            tmpRetDetail.respCode = "-1";
            tmpRetDetail.respInfo = "账号：" + p_req7506.readedDetail.actNum + ",余额查询报错,详情查看日志";
            WriteBankLogLn("账号：" + p_req7506.readedDetail.actNum + ",余额查询报错：" + e.getMessage());
            e.printStackTrace();
        }

        //判断账号有现金池权限，查询查询成员账户现金池余额信息
        //账户余额查询成功才会查询资金池余额
        if (p_req7506.readedDetail.directRight.contains(ENDirectRight.CASHPOOLS.getValue())
                && "0".equals(tmpRetDetail.respCode)
        ) {
            qry7506CashPoolBal(p_req7506, tmpRetDetail);
        }
        retAts.writeRetDetail(tmpRetDetail, p_req7506.isBatch);
    }

    /**
     * 6WZB02 查询成员账户余额信息
     *
     * @param p_req7506
     * @param tmpRetDetail
     */
    private void qry7506CashPoolBal(Req7506BalQry p_req7506, RetAtsBalDetail tmpRetDetail) {
        WriteBankLogLn("进入6WZB02余额查询接口...");
        if (tmpRetDetail.respInfo == null) {
            tmpRetDetail.respInfo = "";
        }
        StringBuilder errorLog = new StringBuilder(tmpRetDetail.respInfo);
        try {
            //赋值通用参数
            CCB02Header bankHeader = new CCB02Header();
            //行方让使用6WCZ02接口查询资产池余额
            bankHeader.TX_CODE = "6WCZ02";
            bankHeader.REQUEST_SN = getQryTransID();

            XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
            //写入通用的头部节点
            writeCommonHeader(xmlWriter, bankHeader);
            xmlWriter.writeStartElement("TX_INFO");
            //集团归集账户，通过配置文件配置
            String cashPoolGroupId = getBankConfig().getValueAsString("cashPoolGroupId");
            if (StringHelper.isNullOrEmpty(cashPoolGroupId)){
                throw new RuntimeException("config/portfiles/CCB02/config.xml中cashPoolGroupId为空，不查询资金池余额");
            }
            xmlWriter.writeElementString("ACC_NO", cashPoolGroupId);
            xmlWriter.writeElementString("ACCT_NO", p_req7506.readedDetail.actNum);
            xmlWriter.writeEndElement();
            xmlWriter.writeEndDocument();
            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString(), p_req7506.reqHeader.transType, "6WCZ02");
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpRetCode = tmpBkReader.getFirstText("/TX/RETURN_CODE");
                    String tmpRetInfo = tmpBkReader.getFirstText("/TX/RETURN_MSG");
                    if (tmpRetCode != null && "000000".equals(tmpRetCode)) {
                        String nodePath = "/TX/TX_INFO/DETAILLIST/DETAILINFO";
                        if (tmpBkReader.read(nodePath)) {
                            tmpRetDetail.cashPoolAvailBal = tmpBkReader.readedXElement.getSingleText("SELF_AMT");
                            tmpRetDetail.cashPoolBal = tmpRetDetail.cashPoolAvailBal;
                        }
                    } else {
                        WriteBankLogLn("资金池余额查询失败，失败原因：" + tmpRetInfo);
                        errorLog.append("资金池余额查询失败，失败原因：" + tmpRetInfo);
                    }
                } else {
                    WriteBankLogLn("资金池余额查询失败，失败原因：" + tmpSbMsg.toString());
                    errorLog.append("资金池余额查询失败，失败原因：" + tmpSbMsg.toString());
                }
            } else {
                WriteBankLogLn("资金池余额查询失败，失败原因：" + tmpStrRet[1]);
                errorLog.append("资金池余额查询失败，失败原因：" + tmpStrRet[1]);
            }
        } catch (Exception e) {
            WriteBankLogLn("资金池余额查询失败，失败原因：" + "账号：" + p_req7506.readedDetail.actNum + ",资金池余额查询报错,详情查看日志");
            errorLog.append("资金池余额查询失败，失败原因：" + "账号：" + p_req7506.readedDetail.actNum + ",资金池余额查询报错,详情查看日志");
        }
        String errorLogStr = errorLog.toString();
        if ((errorLogStr.length() != tmpRetDetail.respInfo.length())) {
            tmpRetDetail.respInfo = errorLogStr;
        }
    }

    @Override
    public RetAts7505HisBalQry d_7505_BalQry(Req7505HisBalQry p_req7505) throws Exception {
        RetAts7505HisBalQry retAts = new RetAts7505HisBalQry(p_req7505.reqHeader);
        retAts.writeStart();//写返回ATS的统一头部信息
        int successCount = 0;//调用银行接口成功次数
        StringBuilder messageStr = new StringBuilder();//错误信息
        int page = 0;//当前查询的页数
        int total_page = 1;//总页数
        int hisBalQryCount = getBankConfig().getValueAsInt("hisBalQryCount", 10);
        String actCur = convertCurToBank(p_req7505.reqHeader.transType, p_req7505.actCur);
        try {
            //赋值通用参数
            CCB02Header bankHeader = new CCB02Header();
            bankHeader.TX_CODE = "NW0100";
            bankHeader.REQUEST_SN = p_req7505.reqHeader.transSeqID;
            while (page < total_page) {
                try {
                    page++;
                    XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
                    //写入通用的头部节点
                    writeCommonHeader(xmlWriter, bankHeader);
                    xmlWriter.writeStartElement("TX_INFO");
                    xmlWriter.writeElementString("ACC_NO", p_req7505.actNum);
                    xmlWriter.writeElementString("CCYCD", actCur);//余额币种
                    xmlWriter.writeElementString("CSHEX_CD", "");//账号钞汇：1-钞；2-汇
                    xmlWriter.writeElementString("STARTDATE", Format.Date8Format.format(p_req7505.getDateFrom()));//YYYYMMDD
                    xmlWriter.writeElementString("ENDDATE", Format.Date8Format.format(p_req7505.getDateTo()));
                    xmlWriter.writeElementString("PAGE", String.valueOf(page));
                    xmlWriter.writeElementString("RECORDNUM", String.valueOf(hisBalQryCount));
                    xmlWriter.writeEndElement();
                    xmlWriter.writeEndDocument();
                    String[] tmpStrRet = sendToBank(xmlWriter.toXmlString(), p_req7505.reqHeader.transType, p_req7505.reqHeader.transType);
                    if (tmpStrRet[0].length() == 0) {
                        StringBuilder tmpSbMsg = new StringBuilder();
                        XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                        if (tmpBkReader != null) {
                            RetAtsHisBalDetail tmpRetDetail = new RetAtsHisBalDetail();
                            String tmpRetCode = tmpBkReader.getFirstText("/TX/RETURN_CODE");
                            String tmpRetInfo = tmpBkReader.getFirstText("/TX/RETURN_MSG");
                            if (tmpRetCode != null && tmpRetCode.equals("000000")) {
                                successCount++;
                                String totalPagStr = tmpBkReader.getFirstText("/TX/TX_INFO/TOTAL_PAGE");
                                total_page = StringHelper.isNullOrEmpty(totalPagStr) ? 1 : Integer.parseInt(totalPagStr);
                                while (tmpBkReader.read("/TX/TX_INFO/DETAILINFO")) {
                                    tmpRetDetail.actBal = tmpBkReader.readedXElement.getSingleText("BALANCE");
                                    tmpRetDetail.availBal = tmpBkReader.readedXElement.getSingleText("AVAL_BALANCE");
                                    tmpRetDetail.balDate = DateHelper.convertD8toD10(tmpBkReader.readedXElement.getSingleText("DATE"));
                                    if (StringHelper.isNullOrEmpty(tmpRetDetail.availBal)) {
                                        tmpRetDetail.availBal = tmpRetDetail.actBal;
                                    }
                                    retAts.writeRetDetail(tmpRetDetail);
                                }
                            } else {
                                messageStr.append("第").append(page).append("页查询成功，银行返回异常：").append(tmpRetInfo).append(";");
                            }
                        } else {
                            messageStr.append("第").append(page).append("页查询异常：").append(tmpSbMsg.toString()).append(";");
                        }
                    } else {
                        messageStr.append("第").append(page).append("页查询不成功：").append(tmpStrRet[1]).append(";");
                    }
                } catch (Exception e) {
                    messageStr.append("第").append(page).append("页查询不成功：").append(e.getMessage()).append(";");
                }
            }
            if (successCount > 0) {
                retAts.writeRespCode("0");
                if (messageStr.toString().length() > 0) {
                    retAts.writeRespInfo(messageStr.toString());
                }
            } else {
                retAts.writeRespCode("-1");
                retAts.writeRespInfo(messageStr.toString());
            }
        } catch (Exception ex) {
            retAts.writeRespCode("-1");
            retAts.writeRespInfo(ex.getMessage());
            WriteBankLogLn(ex);
        } finally {
            retAts.writeEnd();
            return retAts;
        }
    }

}
